/*************************************************************************
	> File Name: montage.cpp
	> Author: 
	> Mail: 
	> Created Time: 2021年05月17日 星期一 15时33分54秒
 ************************************************************************/

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>
#include <vector>

using namespace cv;
using namespace std;

int main(int argc, char const *argv[]) {
    int image_count = 39; //图片数量

    //想要生成的目标图片
    Mat srcImage = imread("../Lake.jpg");
    cout << srcImage.size() << endl;
    //通过resize方法进行尺寸设置
    resize(srcImage, srcImage, Size(1920, 1080));
    cout << srcImage.size() << endl;

    //存放资源文件
    vector<Mat> source_images; 
    char filenames[20];
    for (int i = 1; i <= image_count; i++) {
        Mat src_img;

        //获取文件名
        sprintf(filenames, "../data/cat%d.jpg", i); //最终执行是在build文件夹，相对于build文件夹的位置

        //根据路径读取文件
        src_img = imread(filenames);
        resize(src_img, src_img, Size(30, 30));
        source_images.push_back(src_img);
    }
    //测试：显示图片
    //cout << source_images.size() << endl;
    //imshow("first", source_images[1]);
    
    //制作相关的步骤
    //获取目标图片的宽高
    int width = 1920;  //srcImage.cols  
    int height = srcImage.rows;

    //根据宽高计算横纵需要的图片个数

    //根据颜色进行匹配

    //生成对应的图片

    Mat montageImage;
    resize(srcImage, montageImage, Size(1920, 1080)); //!!保证montgaeImage是匹配的大小
    
    /*
     * 直方图
     *      (1) 根据图片的信息统计出直方图信息
     *      (2) 根据直方图信息进行匹配
     *      (3) 替换对应位置的图片
    */
    int bins = 128; //直方条
    int hist_sizes[] = {bins, bins, bins};
    float range[] = {0, 255};
    const float *ranges[] = {range, range, range};
    int channels[] = {0, 1, 2};

    vector<MatND> hist_list;

    //每张图片的直方图信息统计
    for (int i = 0; i < image_count; i++) {
        MatND hist_RGB;
        Mat frame;
        source_images[i].copyTo(frame);

        //计算直方图信息
        calcHist(&frame, 1, channels, Mat(), hist_RGB, 3, hist_sizes, ranges, true, false);

        hist_list.push_back(hist_RGB);
    }

    //匹配相似度最高的图片
    int number_order = 0;
    for (int y = 0; y < height; y = y + 30) {
        for (int x = 0; x < width; x = x + 30) {
            Mat roiImage = montageImage(Rect(x, y, 30, 30)); 

            MatND hist_roi;

            double match_max; //匹配度
            calcHist(&roiImage, 1, channels, Mat(), hist_roi, 3, hist_sizes, ranges, true, false);

            for (int i = 0; i < image_count; i++) {
                double match = 0;
                match = compareHist(hist_roi, hist_list[i], HISTCMP_CORREL);

                if (match > match_max) {
                    //将匹配度最高的值算出来
                    number_order = i; 
                    match_max = match;
                }
            }
            source_images[number_order].copyTo(roiImage);

            //生成进度
            printf("正在生成中: \033[01;32m %.2f \r", (y / (double)1080 + x / (double)1920 / 100) * 100);
            fflush(stdout);
        }
    }

    Mat dstImage;
    addWeighted(montageImage, 0.2, srcImage, 0.8, 3, dstImage); //montageImage的透明度为0.2, srcImage透明度为0.8, dstImage中2分来源于montageImage, 8分来源于srcImage
    imwrite("dstImage.jpg", dstImage);

    imshow("montage", dstImage);

    waitKey(0);
    return 0;
}


